/**
 * @file Driver_W25Q16.c
 * @brief 
 * @author 2bam 
 * @version 1.0
 * @date 2024-11-25
 * @copyright Copyright (c) 2024  NULL
 * 
 * @change log:
 * Date           Version Author   Describe
 * 2024-11-25     1.0     2bam     first version
 */

/* Includes -------------------------------------------------------------------*/
#include "main.h"
#include "Driver_Spi.h"
#include "Driver_W25Q.h"
#include "Driver_Serial.h"
#include "stdio.h"
/* define ---------------------------------------------------------------------*/

/* typedef --------------------------------------------------------------------*/

/* variables ------------------------------------------------------------------*/

/* Private function prototypes ------------------------------------------------*/


/**
 * @brief 
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QInit(void)
{
    SoftSpiInit();
}

/**
 * @brief 读ID
 * @param  MID         My Param doc
 * @param  DID         My Param doc
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QReadID(uint8_t *MID, uint16_t *DID)
{
    SoftSpiStart();
    SoftSpiSwapByte(W25X_JedecDeviceID);
    *MID = SoftSpiSwapByte(Dummy_Byte);
    *DID = SoftSpiSwapByte(Dummy_Byte);
    *DID <<= 8;
    *DID |= SoftSpiSwapByte(Dummy_Byte);
    SoftSpiStop();
}

/**
 * @brief 写使能
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QWriteEnable(void)
{
    SoftSpiStart();
    SoftSpiSwapByte(W25X_WriteEnable);
    SoftSpiStop();
}

/**
 * @brief 等待芯片空闲
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QWaitBusy(void)
{
    uint32_t timeout = 10000;
    SoftSpiStart();
    /** 读状态寄存器 */
    SoftSpiSwapByte(W25X_ReadStatusReg1);
    /** 芯片为忙就等待一段时间，直到超时 2024-11-26 Tuesday 22:52:10 */
    while(SoftSpiSwapByte(Dummy_Byte)&0x01)
    {
        if((timeout--)==0)
        {
            printf("%s Time out\n",__func__);
            break;
        }
    }
    SoftSpiStop();
}

/**
 * @brief 页编程
 * @param  addr        页地址
 * @param  data_array  要发送的数据指针
 * @param  count       发送字节数量
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QPageProgram(uint32_t addr, uint8_t *data_array, uint16_t count)
{
    /** 写使能 */
    W25QWriteEnable();

    SoftSpiStart();
    SoftSpiSwapByte(W25X_PageProgram);
    /** 发送页地址 */
    SoftSpiSwapByte(addr>>16);
    SoftSpiSwapByte(addr>>8);
    SoftSpiSwapByte(addr);
    /** 发送数据 */
    for (uint16_t i = 0; i < count; i++)
    {
        SoftSpiSwapByte(data_array[i]);
    }
    SoftSpiStop();
    /** 等待忙 */
    W25QWaitBusy();
}

/**
 * @brief 扇区擦除
 * @param  addr        My Param doc
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QSectorErase(uint32_t addr)
{
    /** 写使能 */
    W25QWriteEnable();

    SoftSpiStart();
    SoftSpiSwapByte(W25X_SectorErase);
    /** 发送地址 */
    SoftSpiSwapByte(addr>>16);
    SoftSpiSwapByte(addr>>8);
    SoftSpiSwapByte(addr);
    SoftSpiStop();

    /** 等待忙 */
    W25QWaitBusy();
}

/**
 * @brief 读取数据
 * @param  addr        My Param doc
 * @param  data_array  My Param doc
 * @param  count       My Param doc
 * @date 2024-11-26
 * @author 2bam 
 */
void W25QReadData(uint32_t addr, uint8_t *data_array, uint32_t count)
{
    SoftSpiStart();
    SoftSpiSwapByte(W25X_ReadData);
    /** 发送地址 */
    SoftSpiSwapByte(addr>>16);
    SoftSpiSwapByte(addr>>8);
    SoftSpiSwapByte(addr);
    for (size_t i = 0; i < count; i++)
    {
        data_array[i] = SoftSpiSwapByte(Dummy_Byte);
    }
    SoftSpiStop();
}